home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
utils
/
diff.arc
/
DIFF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-08-03
|
35KB
|
1,574 lines
/*
* diff.c - public domain context diff program
*
*/
#ifdef TURBO
#include <alloc.h>
#include <errno.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#else /* !TURBO */
#include <stdio.h>
#include <ctype.h>
#endif /* TURBO */
#ifdef atarist
#define remove unlink
#endif
#ifdef vms
#include <ssdef.h>
#include <stsdef.h>
#define IO_SUCCESS (SS | STS)
#define IO_ERROR SS
#endif /* vms */
/*
* Note: IO_SUCCESS and IO_ERROR are defined in the Decus C stdio.h file
*/
#ifndef IO_SUCCESS
#define IO_SUCCESS 0
#endif /* IO_SUCCESS */
#ifndef IO_ERROR
#define IO_ERROR 1
#endif /* IO_ERROR */
#define EOS 0
#ifdef unix
char temfile[L_tmpnam];
char *tmpnam();
#define TEMPFILE (temfile[0]? temfile: (tmpnam(temfile), temfile))
#else /* unix */
#define TEMPFILE "diff.tmp"
#endif /* unix */
#define TRUE 1
#define FALSE 0
#ifdef pdp11
#define short int
#endif /* pdp11 */
typedef struct candidate {
int b; /* Line in fileB */
int a; /* Line in fileA */
int link; /* Previous candidate */
} CANDIDATE;
typedef struct line {
unsigned short hash; /* Hash value etc. */
short serial; /* Line number */
} LINE;
LINE *file[2]; /* Hash/line for total file */
#define fileA file[0]
#define fileB file[1]
LINE *sfile[2]; /* Hash/line after prefix */
#define sfileA sfile[0]
#define sfileB sfile[1]
int len[2]; /* Actual lines in each file */
#define lenA len[0]
#define lenB len[1]
int slen[2]; /* Squished lengths */
#define slenA slen[0]
#define slenB slen[1]
int prefix; /* Identical lines at start */
int suffix; /* Identical lenes at end */
FILE *infd[2] = {NULL, NULL}; /* Input file identifiers */
FILE *tempfd; /* Temp for input redirection */
extern long ftell();
extern FILE *fopen();
#ifdef TURBO
extern void *malloc();
#else /* !TURBO */
extern char *malloc();
#endif /* TURBO */
char *fgetss();
unsigned short hash();
#ifdef AMIGA
/* Define these types for Amiga C */
char *savptr;
int savsiz;
char *wrk;
char *wrk2;
int cpysiz;
#endif /* AMIGA */
/*
* The following vectors overlay the area defined by fileA
*/
short *class; /* Unsorted line numbers */
int *klist; /* Index of element in clist */
CANDIDATE *clist; /* Storage pool for candidates */
int clength = 0; /* Number of active candidates */
#define CSIZE_INC 50 /* How many to allocate each time we have to */
int csize = CSIZE_INC; /* Current size of storage pool */
int *match; /* Longest subsequence */
long *oldseek; /* Seek position in file A */
/*
* The following vectors overlay the area defined by fileB
*/
short *member; /* Concatenated equiv. classes */
long *newseek; /* Seek position in file B */
char *textb; /* Input from file2 for check */
/*
* Global variables
*/
int eflag = FALSE; /* Edit script requested */
int bflag = FALSE; /* Blank supress requested */
int cflag = FALSE; /* Context printout */
int iflag = FALSE; /* Ignore case requested */
char text[257]; /* Input line from file1 */
extern char *myalloc(); /* Storage allocator */
extern char *compact(); /* Storage compactor */
#ifdef DEBUG
#ifndef OSK
#define TIMING
#endif /* OSK */
#endif /* DEBUG */
#ifdef TIMING
extern long time();
#ifndef atarist
/* what the fuck is this??? */
extern char *4532mend;
#endif
long totaltime;
long sectiontime;
char *mstart;
#endif /* TIMING */
void free();
void exit();
#ifndef OSK
void perror();
#endif /* OSK */
/*
* Diff main program
*/
main(argc, argv)
int argc;
char **argv;
{
register int i;
register char *ap;
#ifdef OSK
extern int _memmins;
_memmins = 16 * 1024; /* tell OSK we will malloc a lot */
#endif /* OSK */
#ifdef TIMING
sectiontime = time(&totaltime);
#endif /* TIMING */
#ifdef vms
argc = getredirection(argc, argv);
#endif /* vms */
while (argc > 1 && *(ap = argv[1]) == '-' && *++ap != EOS) {
while (*ap != EOS) {
switch ((*ap++)) {
case 'b':
bflag++;
break;
case 'c':
if (*ap > '0' && *ap <= '9')
cflag = *ap++ - '0';
else
cflag = 3;
break;
case 'e':
eflag++;
break;
case 'i':
iflag++;
break;
default:
fprintf(stderr,
"Warning, bad option '%c'\n",
ap[-1]);
break;
}
}
argc--;
argv++;
}
if (argc != 3)
error("Usage: diff [-options] file1 file2");
if (cflag && eflag) {
fprintf(stderr,
"Warning, -c and -e are incompatible, -c supressed.\n");
cflag = FALSE;
}
argv++;
for (i = 0; i <= 1; i++) {
if (argv[i][0] == '-' && argv[i][1] == EOS) {
infd[i] = stdin;
if ((tempfd = fopen(TEMPFILE, "w")) == NULL)
cant(TEMPFILE, "work", 1);
} else {
infd[i] = fopen(argv[i], "r");
if (!infd[i])
cant(argv[i], "input", 2); /* Fatal error */
}
}
if (infd[0] == stdin && infd[1] == stdin)
error("Can't diff two things both on standard input.");
if (infd[0] == NULL && infd[1] == NULL) {
cant(argv[0], "input", 0);
cant(argv[1], "input", 1);
}
#ifdef vms
else if (infd[1] == NULL)
opendir(1, &argv[1], infd[0]);
else if (infd[0] == NULL)
opendir(0, &argv[0], infd[1]);
#endif /* vms */
/*
* Read input, building hash tables.
*/
input(0);
input(1);
squish();
#ifdef DEBUG
printf("before sort\n");
for (i = 1; i <= slenA; i++)
printf("sfileA[%d] = %6d %06o\n",
i, sfileA[i].serial, sfileA[i].hash);
for (i = 1; i <= slenB; i++)
printf("sfileB[%d] = %6d %06o\n",
i, sfileB[i].serial, sfileB[i].hash);
#endif /* DEBUG */
sort(sfileA, slenA);
sort(sfileB, slenB);
#ifdef TIMING
ptime("input");
#endif /* TIMING */
#ifdef DEBUG
printf("after sort\n");
for (i = 1; i <= slenA; i++)
printf("sfileA[%d] = %6d %06o\n",
i, sfileA[i].serial, sfileB[i].hash);
for (i = 1; i <= slenB; i++)
printf("sfileB[%d] = %6d %06o\n",
i, sfileB[i].serial, sfileB[i].hash);
#endif /* DEBUG */
/*
* Build equivalence classes.
*/
member = (short *) fileB;
equiv();
member = (short *) compact((char *) member, (slenB + 2) * sizeof(int),
"squeezing member vector");
/*
* Reorder equivalence classes into array class[]
*/
class = (short *) fileA;
unsort();
class = (short *) compact((char *) class, (slenA + 2) * sizeof(int),
"compacting class vector");
#ifdef TIMING
ptime("equiv/unsort");
#endif /* TIMING */
/*
* Find longest subsequences
*/
klist = (int *) myalloc((slenA + 2) * sizeof(int), "klist");
clist = (CANDIDATE *) myalloc(csize * sizeof(CANDIDATE), "clist");
i = subseq();
#ifndef OSK
free((char *) member);
free((char *) class);
#else /* OSK */
free((char *) member - sizeof(int));
free((char *) class - sizeof(int));
#endif /* OSK */
match = (int *) myalloc((lenA + 2) * sizeof(int), "match");
unravel(klist[i]);
#ifndef OSK
free((char *) clist);
free((char *) klist);
#else /* OSK */
free((char *) clist - sizeof(int));
free((char *) klist - sizeof(int));
#endif /* OSK */
#ifdef TIMING
ptime("subsequence/unravel");
#endif /* TIMING */
/*
* Check for fortuitous matches and output differences
*/
oldseek = (long *) myalloc((lenA + 2) * sizeof(*oldseek), "oldseek");
newseek = (long *) myalloc((lenB + 2) * sizeof(*newseek), "newseek");
textb = myalloc(sizeof text, "textbuffer");
if (check(argv[0], argv[1]))
fprintf(stderr, "Spurious match, output is not optimal\n");
#ifdef TIMING
ptime